<template>
  <div class="mask-editor">
    <div class="sidebar">
      <div class="product-image-section">
        <div class="image-wrapper">
          <el-upload
            class="upload"
            :show-file-list="false"
            :on-change="handleProductImageChange"
            accept="image/*"
          >
            <img v-if="productImageUrl" :src="productImageUrl" class="preview-img" />
            <div v-else class="upload-placeholder">
              <el-button 
                type="primary" 
                size="medium"
                class="upload-product-btn-prominent"
              >
                <el-icon><Upload /></el-icon>
                上传产品图
              </el-button>
            </div>
          </el-upload>
          <!-- 产品图画布 -->
          <canvas
            v-if="productImageUrl"
            ref="productCanvasRef"
            :width="350"
            :height="350"
            class="product-mask-canvas"
            @mousedown="startProductDraw"
            @mousemove="drawingProduct"
            @mouseup="endDraw"
            @mouseleave="endDraw"
            @touchstart="startProductDraw"
            @touchmove="drawingProduct"
            @touchend="endDraw"
          ></canvas>
        </div>
      </div>
      
      <!-- 工具区域 - 放在产品图下方 -->
      <div class="tools">
        <el-radio-group v-model="tool" size="small">
          <el-radio-button label="brush">画笔</el-radio-button>
          <el-radio-button label="eraser">橡皮擦</el-radio-button>
        </el-radio-group>
        <div class="slider-label">粗细</div>
        <el-slider v-model="brushSize" :min="5" :max="60" />
      </div>
      
    </div>
    <div class="canvas-area">
      <div class="canvas-header">
        用画笔将需要迁移的产品和替换的区域整个涂抹起来
      </div>
      <div class="canvas-main">
        <div class="canvas-bg-checkerboard"></div>
        <el-upload
          v-if="!modelImageUrl"
          ref="modelUploadRef"
          class="upload-center"
          :show-file-list="false"
          :on-change="handleModelImageChange"
          accept="image/*"
        >
          <div class="upload-center-btn">
            <!-- 上传模特图放在上面且权重相同 -->
            <el-button 
              type="primary" 
              size="medium"
              @click.stop="triggerModelImageUpload"
              class="upload-model-btn-prominent"
            >
              <el-icon><Upload /></el-icon>
              上传模特图
            </el-button>
            
            <!-- <div class="upload-divider">或</div>
            <el-button 
              type="primary" 
              size="medium"
              @click.stop="handleOpenDigitalHumanDialog"
              class="select-digital-human-btn-prominent"
            >
              <el-icon><User /></el-icon>
              选择模版
            </el-button> -->
          </div>
        </el-upload>
        <div v-else class="canvas-img-wrap">
          <div class="model-image-container">
            <img :src="modelImageUrl" class="canvas-img" ref="modelImageRef" />
            <canvas
              ref="canvasRef"
              class="mask-canvas"
              @mousedown="startDraw"
              @mousemove="drawing"
              @mouseup="endDraw"
              @mouseleave="endDraw"
              @touchstart="startDraw"
              @touchmove="drawing"
              @touchend="endDraw"
            ></canvas>
            <!-- 显示图片来源信息 -->
            <div class="image-source-info">
              <span v-if="selectedTemplate">
                模版: {{ getTemplateDisplayName(selectedTemplate) }}
              </span>
              <span v-else>
                已上传模特图
              </span>
              <el-button 
                type="danger" 
                size="small" 
                @click="clearModelImage"
                class="clear-btn"
              >
                清除
              </el-button>
            </div>
          </div>
        </div>
        <!-- 右下角操作按钮组 -->
        <div class="canvas-actions">
          <!-- Removed the '换脸' button -->
        </div>
      </div>
      <!-- 底部吸底操作栏 -->
      <div class="canvas-footer-bar">
        <!--
        <div class="footer-left">
          <el-button class="template-btn" size="large" @click="handleOpenDigitalHumanDialog">
            {{ selectedTemplate ? '更换模版' : '选择模版' }}
          </el-button>
        </div>
        -->
        <div class="footer-center">
          <el-button type="primary" class="generate-btn" :disabled="!modelImageUrl && !selectedTemplate" @click="handleGenerate">
            生成 <span class="points-text">8积分</span>
          </el-button>
        </div>
        <div class="footer-right">
          <el-button class="task-list-btn" size="large" @click="goToTaskList">
            📋 万物迁移列表
          </el-button>
        </div>
      </div>
    </div>

    <!-- 模版选择弹窗 -->
    <el-dialog
      v-model="showDigitalHumanDialog"
      title="选择模板"
      width="80%"
      class="digital-human-dialog"
    >
      <!-- 分类筛选 -->
      <div class="category-section">
        <h4 class="section-subtitle">分类筛选</h4>
        <div class="category-list">
          <div v-if="categoryLoading" class="category-item disabled">
            加载中...
          </div>
          <div 
            v-else
            class="category-item"
            :class="{ active: selectedCategory === '' }"
            @click="handleCategoryChange('')"
          >
            全部
          </div>
          <div 
            v-for="category in categoryList" 
            :key="category.id" 
            class="category-item"
            :class="{ active: selectedCategory === category.id }"
            @click="handleCategoryChange(category.id)"
          >
            {{ category.name }}
          </div>
        </div>
      </div>

      <!-- 模板列表 -->
      <div class="template-grid" @scroll="handleTemplateScroll">
        <div
          v-for="template in templateList"
          :key="template.template_id"
          class="template-card"
          :class="{ 'selected': selectedTemplateInDialog && selectedTemplateInDialog.template_id === template.template_id }"
          @click="handleSelectTemplate(template)"
        >
          <div class="template-image">
            <img 
              :src="getTemplateImageUrl(template)" 
              :alt="template.template_name || template.templateName" 
              @error="handleImageError"
            />
          </div>
          <div class="template-info">
            <div class="template-name">{{ getTemplateDisplayName(template) }}</div>
            <div class="template-desc" v-if="template.description || template.desc">
              {{ template.description || template.desc }}
            </div>
            <div class="template-desc" v-else>
              {{ template.style || 'Pro' }} 风格
            </div>
          </div>
        </div>
        <div v-if="templateLoading" class="loading-more">
          <el-icon class="is-loading"><Loading /></el-icon>
          <span>加载中...</span>
        </div>
      </div>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showDigitalHumanDialog = false">取消</el-button>
          <el-button 
            type="primary" 
            @click="confirmDigitalHumanSelection"
            :disabled="!selectedTemplateInDialog"
          >
            确定
          </el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, watch, onUnmounted } from 'vue'
import { ElMessage, ElLoading, ElMessageBox } from 'element-plus'
import { Loading, User, Upload, VideoPlay } from '@element-plus/icons-vue'
import { useRouter } from 'vue-router'
import { API_CONFIG, apiRequest } from '../../config/api.js'

const router = useRouter()

const productImageUrl = ref('')
const modelImageUrl = ref('')
const tool = ref('brush') // brush or eraser
const brushSize = ref(30)
const drawingState = reactive({
  drawing: false,
  lastX: 0,
  lastY: 0,
})
const canvasRef = ref(null)
const productCanvasRef = ref(null)
const modelImageRef = ref(null)
const modelUploadRef = ref(null)
const canvasWidth = 480
const canvasHeight = 600

// 新增：遮罩相关状态
const productMaskCanvas = ref(null)
const modelMaskCanvas = ref(null)
const originalProductSize = ref({ width: 0, height: 0 })
const originalModelSize = ref({ width: 0, height: 0 })

// 新增：上传状态标志
const productUploading = ref(false)
const modelUploading = ref(false)

// 新增：模版选择相关状态
const showDigitalHumanDialog = ref(false)
const categoryList = ref([])
const templateList = ref([])
const selectedCategory = ref('')
const categoryLoading = ref(false)
const templateLoading = ref(false)
const templatePageNo = ref(1)
const templateHasMore = ref(true)
const pageSize = 20
const selectedTemplate = ref(null) // 选中的模版
const selectedTemplateInDialog = ref(null) // 弹窗中临时选择的模版

// 新增：存储上传文件的ID
const productImageFileId = ref('')
const modelImageFileId = ref('')

function openImage(url) {
  // 使用 Element Plus 图片预览
  const img = new Image()
  img.src = url
  const w = window.open('about:blank')
  if (w) {
    w.document.write('<title>预览</title>')
    w.document.body.style.background = '#000'
    w.document.body.style.margin = '0'
    const el = w.document.createElement('img')
    el.src = url
    el.style.maxWidth = '100%'
    el.style.maxHeight = '100vh'
    el.style.display = 'block'
    el.style.margin = '0 auto'
    w.document.body.appendChild(el)
  }
}

// 生成模板显示名称
function getTemplateDisplayName(template) {
  if (!template) return ''
  
  if (template.template_name || template.templateName || template.name) {
    return template.template_name || template.templateName || template.name
  }
  
  // 根据分类和风格生成名称
  const categoryName = template.category_name || template.templateCategoryList?.[0]?.categoryName || ''
  const style = template.style || 'Pro'
  
  if (categoryName) {
    // 将英文分类名转换为中文
    const categoryTranslations = {
      "Women's top": "女士上装",
      "Men's top": "男士上装",
      "Women's bottoms": "女士下装",
      "Men's bottoms": "男士下装",
      "Dress": "连衣裙"
    }
    const chineseName = categoryTranslations[categoryName] || categoryName
    return `${chineseName} ${style}风格`
  }
  
  return `${style}风格模板`
}

// 调整画布尺寸以匹配图片
function resizeCanvasToImage() {
  const img = modelImageRef.value
  const canvas = canvasRef.value
  if (!img || !canvas) return
  
  // 等待图片加载完成
  if (img.complete) {
    const rect = img.getBoundingClientRect()
    canvas.width = rect.width
    canvas.height = rect.height
    canvas.style.width = rect.width + 'px'
    canvas.style.height = rect.height + 'px'
    
    // 重新初始化遮罩画布
    if (originalModelSize.value.width && originalModelSize.value.height) {
      initModelMaskCanvas()
    }
  } else {
    img.onload = () => {
      const rect = img.getBoundingClientRect()
      canvas.width = rect.width
      canvas.height = rect.height
      canvas.style.width = rect.width + 'px'
      canvas.style.height = rect.height + 'px'
      
      // 重新初始化遮罩画布
      if (originalModelSize.value.width && originalModelSize.value.height) {
        initModelMaskCanvas()
      }
    }
  }
}

// 上传产品图
async function handleProductImageChange(file) {
  const raw = file.raw || file
  if (!raw.type.startsWith('image/')) {
    ElMessage.error('请上传图片文件')
    return
  }

  // 防止重复上传
  if (productUploading.value) {
    return
  }
  productUploading.value = true

  // 显示加载中
  const loading = ElLoading.service({
    lock: true,
    text: '正在上传图片...',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    // 1. 获取上传凭证
    const response = await apiRequest(API_CONFIG.ENDPOINTS.GET_UPLOAD_CREDENTIAL, {
      method: 'GET'
    })

    if (response.code !== 200 || !response.data) {
      throw new Error('获取上传凭证失败')
    }

    const { uploadUrl, fileId, fileName } = response.data

    // 2. 上传图片到 S3
    const uploadResponse = await fetch(uploadUrl, {
      method: 'PUT',
      body: raw,
      headers: {
        'Content-Type': raw.type
      }
    })

    if (!uploadResponse.ok) {
      throw new Error('图片上传失败')
    }

    // 3. 保存文件ID和设置预览
    productImageFileId.value = fileId
    
    const img = new Image()
    img.onload = () => {
      originalProductSize.value = { width: img.width, height: img.height }
      initProductMaskCanvas()
    }
    img.src = URL.createObjectURL(raw)
    productImageUrl.value = img.src

    ElMessage.success('产品图上传成功')

  } catch (error) {
    console.error('上传失败:', error)
    ElMessage.error(error.message || '上传失败，请重试')
  } finally {
    loading.close()
    productUploading.value = false
  }
}

// 上传模特图
async function handleModelImageChange(file) {
  const raw = file.raw || file
  if (!raw.type.startsWith('image/')) {
    ElMessage.error('请上传图片文件')
    return
  }

  // 防止重复上传
  if (modelUploading.value) {
    return
  }
  modelUploading.value = true

  // 显示加载中
  const loading = ElLoading.service({
    lock: true,
    text: '正在上传图片...',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    // 1. 获取上传凭证
    const response = await apiRequest(API_CONFIG.ENDPOINTS.GET_UPLOAD_CREDENTIAL, {
      method: 'GET'
    })

    if (response.code !== 200 || !response.data) {
      throw new Error('获取上传凭证失败')
    }

    const { uploadUrl, fileId, fileName } = response.data

    // 2. 上传图片到 S3
    const uploadResponse = await fetch(uploadUrl, {
      method: 'PUT',
      body: raw,
      headers: {
        'Content-Type': raw.type
      }
    })

    if (!uploadResponse.ok) {
      throw new Error('图片上传失败')
    }

    // 3. 保存文件ID和设置预览
    modelImageFileId.value = fileId
    
    const img = new Image()
    img.onload = () => {
      originalModelSize.value = { width: img.width, height: img.height }
      drawBg()
      initModelMaskCanvas()
      // 调整画布尺寸
      setTimeout(() => {
        resizeCanvasToImage()
      }, 100)
    }
    img.src = URL.createObjectURL(raw)
    modelImageUrl.value = img.src

    ElMessage.success('模特图上传成功')

  } catch (error) {
    console.error('上传失败:', error)
    ElMessage.error(error.message || '上传失败，请重试')
  } finally {
    loading.close()
    modelUploading.value = false
  }
}

// 初始化产品图遮罩画布
function initProductMaskCanvas() {
  if (!originalProductSize.value.width || !originalProductSize.value.height) return
  
  const canvas = document.createElement('canvas')
  canvas.width = originalProductSize.value.width
  canvas.height = originalProductSize.value.height
  const ctx = canvas.getContext('2d')
  // 初始化为透明背景，而不是黑色
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  productMaskCanvas.value = canvas
  
  // 初始化产品图显示画布
  setTimeout(() => {
    initProductDisplayCanvas()
  }, 100)
}

// 初始化产品图显示画布
function initProductDisplayCanvas() {
  const canvas = productCanvasRef.value
  if (!canvas || !productImageUrl.value) return
  
  const ctx = canvas.getContext('2d')
  // 清除画布，不绘制背景图，避免双层显示
  ctx.clearRect(0, 0, canvas.width, canvas.height)
}

// 初始化模特图遮罩画布
function initModelMaskCanvas() {
  if (!originalModelSize.value.width || !originalModelSize.value.height) return
  
  const canvas = document.createElement('canvas')
  canvas.width = originalModelSize.value.width
  canvas.height = originalModelSize.value.height
  const ctx = canvas.getContext('2d')
  // 初始化为透明背景，而不是黑色
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  modelMaskCanvas.value = canvas
}

// 绘制背景图（模特图）
function drawBg() {
  if (!modelImageUrl.value) return
  const canvas = canvasRef.value
  if (!canvas) return
  const ctx = canvas.getContext('2d')
  // 只清除画布，不绘制背景图到画布上
  ctx.clearRect(0, 0, canvas.width, canvas.height)
}

// 画笔/橡皮擦绘制
function getPos(e) {
  const canvas = canvasRef.value
  if (!canvas) return { x: 0, y: 0, inBounds: false }
  
  const rect = canvas.getBoundingClientRect()
  const clientX = e.touches ? e.touches[0].clientX : e.clientX
  const clientY = e.touches ? e.touches[0].clientY : e.clientY
  
  const x = clientX - rect.left
  const y = clientY - rect.top
  
  // 检查是否在画布范围内
  const inBounds = x >= 0 && x <= rect.width && y >= 0 && y <= rect.height
  
  return {
    x: x,
    y: y,
    inBounds: inBounds
  }
}

// 获取产品图画布位置
function getProductPos(e) {
  const rect = productCanvasRef.value?.getBoundingClientRect()
  if (!rect) return null
  const clientX = e.touches ? e.touches[0].clientX : e.clientX
  const clientY = e.touches ? e.touches[0].clientY : e.clientY
  return {
    x: clientX - rect.left,
    y: clientY - rect.top,
  }
}

function startDraw(e) {
  if (!modelImageUrl.value) return
  e.preventDefault()
  const pos = getPos(e)
  if (!pos.inBounds) return
  
  drawingState.drawing = true
  drawingState.lastX = pos.x
  drawingState.lastY = pos.y
}

// 产品图开始绘制
function startProductDraw(e) {
  if (!productImageUrl.value) return
  e.preventDefault()
  drawingState.drawing = true
  const pos = getProductPos(e)
  if (pos) {
    drawingState.lastX = pos.x
    drawingState.lastY = pos.y
  }
}

function drawing(e) {
  if (!drawingState.drawing) return
  e.preventDefault()
  
  const pos = getPos(e)
  if (!pos.inBounds) {
    // 如果超出边界，停止绘制
    endDraw()
    return
  }
  
  const canvas = canvasRef.value
  const ctx = canvas.getContext('2d')
  ctx.lineCap = 'round'
  ctx.lineJoin = 'round'
  ctx.lineWidth = brushSize.value
  
  // 修复橡皮擦逻辑 - 橡皮擦应该擦除画布上的内容，而不是背景图
  if (tool.value === 'brush') {
    ctx.globalAlpha = 0.5
    ctx.strokeStyle = '#ffe600'
    ctx.globalCompositeOperation = 'source-over'
  } else {
    ctx.globalAlpha = 1
    ctx.strokeStyle = 'rgba(255, 255, 255, 1)'
    ctx.globalCompositeOperation = 'destination-out'
  }

  ctx.beginPath()
  ctx.moveTo(drawingState.lastX, drawingState.lastY)
  ctx.lineTo(pos.x, pos.y)
  ctx.stroke()
  
  // 同时在遮罩画布上绘制
  updateModelMask(drawingState.lastX, drawingState.lastY, pos.x, pos.y)
  
  drawingState.lastX = pos.x
  drawingState.lastY = pos.y
}

// 产品图绘制
function drawingProduct(e) {
  if (!drawingState.drawing) return
  e.preventDefault()
  const pos = getProductPos(e)
  if (!pos) return
  
  // 在产品图画布上显示绘制效果
  const canvas = productCanvasRef.value
  if (canvas) {
    const ctx = canvas.getContext('2d')
    ctx.lineCap = 'round'
    ctx.lineJoin = 'round'
    ctx.lineWidth = brushSize.value
    ctx.globalAlpha = 0.5
    
    if (tool.value === 'brush') {
      ctx.strokeStyle = '#ffe600'
      ctx.globalCompositeOperation = 'source-over'
    } else {
      ctx.strokeStyle = 'rgba(255, 255, 255, 1)'
      ctx.globalCompositeOperation = 'destination-out'
    }
    
    ctx.beginPath()
    ctx.moveTo(drawingState.lastX, drawingState.lastY)
    ctx.lineTo(pos.x, pos.y)
    ctx.stroke()
  }
  
  // 在产品图遮罩上绘制
  updateProductMask(drawingState.lastX, drawingState.lastY, pos.x, pos.y)
  
  drawingState.lastX = pos.x
  drawingState.lastY = pos.y
}

// 更新模特图遮罩
function updateModelMask(lastX, lastY, x, y) {
  if (!modelMaskCanvas.value) return
  
  const maskCtx = modelMaskCanvas.value.getContext('2d')
  const canvas = canvasRef.value
  const img = modelImageRef.value
  
  if (!canvas || !img) return
  
  // 计算缩放比例 - 使用画布的实际尺寸而不是getBoundingClientRect
  const scaleX = originalModelSize.value.width / canvas.width
  const scaleY = originalModelSize.value.height / canvas.height
  
  maskCtx.lineCap = 'round'
  maskCtx.lineJoin = 'round'
  maskCtx.lineWidth = brushSize.value * Math.max(scaleX, scaleY)
  maskCtx.strokeStyle = tool.value === 'brush' ? 'white' : 'black'
  
  maskCtx.beginPath()
  maskCtx.moveTo(lastX * scaleX, lastY * scaleY)
  maskCtx.lineTo(x * scaleX, y * scaleY)
  maskCtx.stroke()
}

// 更新产品图遮罩
function updateProductMask(lastX, lastY, x, y) {
  if (!productMaskCanvas.value) return
  
  const maskCtx = productMaskCanvas.value.getContext('2d')
  const canvas = productCanvasRef.value
  
  if (!canvas) return
  
  // 使用画布的实际尺寸计算缩放比例
  const scaleX = originalProductSize.value.width / canvas.width
  const scaleY = originalProductSize.value.height / canvas.height
  
  maskCtx.lineCap = 'round'
  maskCtx.lineJoin = 'round'
  maskCtx.lineWidth = brushSize.value * Math.max(scaleX, scaleY)
  maskCtx.strokeStyle = tool.value === 'brush' ? 'white' : 'black'
  
  maskCtx.beginPath()
  maskCtx.moveTo(lastX * scaleX, lastY * scaleY)
  maskCtx.lineTo(x * scaleX, y * scaleY)
  maskCtx.stroke()
}

function endDraw() {
  drawingState.drawing = false
  // 恢复默认
  const ctx = canvasRef.value?.getContext('2d')
  if (ctx) {
    ctx.globalAlpha = 1
    ctx.globalCompositeOperation = 'source-over'
  }
  
  const productCtx = productCanvasRef.value?.getContext('2d')
  if (productCtx) {
    productCtx.globalAlpha = 1
    productCtx.globalCompositeOperation = 'source-over'
  }
}

// 上传遮罩图片
async function uploadMaskImage(maskCanvas, imageName) {
  if (!maskCanvas) {
    ElMessage.error('没有遮罩数据')
    return null
  }

  const loading = ElLoading.service({
    lock: true,
    text: '正在上传遮罩图片...',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    // 1. 获取上传凭证
    const response = await apiRequest(API_CONFIG.ENDPOINTS.GET_UPLOAD_CREDENTIAL, {
      method: 'GET'
    })

    if (response.code !== 200 || !response.data) {
      throw new Error('获取上传凭证失败')
    }

    const { uploadUrl, fileId, fileName } = response.data

    // 2. 将canvas转换为blob
    const blob = await new Promise(resolve => {
      maskCanvas.toBlob(resolve, 'image/png')
    })

    // 3. 上传遮罩图片到 S3
    const uploadResponse = await fetch(uploadUrl, {
      method: 'PUT',
      body: blob,
      headers: {
        'Content-Type': 'image/png'
      }
    })

    if (!uploadResponse.ok) {
      throw new Error('遮罩图片上传失败')
    }

    ElMessage.success(`${imageName}遮罩上传成功`)
    return { fileId, fileName, uploadUrl }

  } catch (error) {
    console.error('遮罩上传失败:', error)
    ElMessage.error(error.message || '遮罩上传失败，请重试')
    return null
  } finally {
    loading.close()
  }
}

// 每次模特图变化都重绘
watch(modelImageUrl, () => {
  setTimeout(() => {
    drawBg()
    resizeCanvasToImage()
  }, 100)
})

async function handleGenerate() {
  // 检查必要条件
  if (!modelImageUrl.value) {
    ElMessage.warning('请先上传模特图或选择模版')
    return
  }

  if (!productImageUrl.value) {
    ElMessage.warning('请先上传产品图')
    return
  }

  // 显示加载状态
  const loading = ElLoading.service({
    lock: true,
    text: '正在生成图片...',
    background: 'rgba(0, 0, 0, 0.7)'
  })

  try {
    // 1. 上传产品图遮罩
    let productMaskResult = null
    if (productMaskCanvas.value) {
      productMaskResult = await uploadMaskImage(productMaskCanvas.value, '产品图')
      if (!productMaskResult) {
        throw new Error('产品图遮罩上传失败')
      }
    }

    // 2. 上传模特图遮罩
    let modelMaskResult = null
    if (modelMaskCanvas.value) {
      modelMaskResult = await uploadMaskImage(modelMaskCanvas.value, '模特图')
      if (!modelMaskResult) {
        throw new Error('模特图遮罩上传失败')
      }
    }

    // 3. 准备任务提交参数
    const taskParams = {}

    // 产品图相关参数
    if (productImageFileId.value) {
      taskParams.productImageFileId = productImageFileId.value
    } else {
      throw new Error('产品图文件ID缺失，请重新上传产品图')
    }
    
    if (productMaskResult) {
      taskParams.productMaskFileId = productMaskResult.fileId
    }

    // 模版相关参数 - 二选一
    if (selectedTemplate.value) {
      // 用户选择了模版
      taskParams.templateId = selectedTemplate.value.template_id
      // 模版遮罩参数
      if (modelMaskResult) {
        taskParams.templateMaskFileId = modelMaskResult.fileId
      }
    } else if (modelImageFileId.value) {
      // 用户上传了自己的模特图
      taskParams.templateImageFileId = modelImageFileId.value
      // 模特图遮罩参数
      if (modelMaskResult) {
        taskParams.templateMaskFileId = modelMaskResult.fileId
      }
    } else {
      throw new Error('请选择模板或上传模特图')
    }

    console.log('任务提交参数:', taskParams)

    // 4. 提交任务
    const response = await apiRequest('/product_background/task/submit', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(taskParams)
    })

    if (response.code === 200) {
      console.log('任务提交成功:', response.data)
      
      // 显示确认提示
      ElMessageBox.confirm(
        '正在合成图片，请跳转列表，等待图片生成后，点击任务，进行视频生成',
        '提交成功',
        {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'success',
          center: true
        }
      ).then(() => {
        // 用户点击确定后跳转到万物迁移列表
        goToTaskList()
      }).catch(() => {
        // 用户点击取消，不做任何操作
        console.log('用户取消跳转')
      })
      
      // 开始轮询任务状态
      if (response.data.taskId) {
        pollTaskStatus(response.data.taskId)
      }
    } else {
      throw new Error(response.msg || '任务提交失败')
    }

  } catch (error) {
    console.error('生成失败:', error)
    ElMessage.error(error.message || '生成失败，请重试')
  } finally {
    loading.close()
  }
}

// 轮询任务状态（可选功能）
async function pollTaskStatus(taskId) {
  const maxAttempts = 30 // 最多轮询30次
  const interval = 2000 // 每2秒轮询一次
  let attempts = 0

  const poll = async () => {
    try {
      attempts++
      const response = await apiRequest(`/productAnyShoot/task/status/${taskId}`, {
        method: 'GET'
      })

      if (response.code === 200) {
        const { status, result } = response.data
        
        if (status === 'completed') {
          ElMessage.success('图片生成完成！')
          console.log('生成结果:', result)
          // 这里可以显示生成的图片
          return
        } else if (status === 'failed') {
          ElMessage.error('图片生成失败')
          return
        } else if (status === 'processing' && attempts < maxAttempts) {
          // 继续轮询
          setTimeout(poll, interval)
        } else if (attempts >= maxAttempts) {
          ElMessage.warning('生成时间较长，请稍后查看结果')
        }
      }
    } catch (error) {
      console.error('轮询任务状态失败:', error)
    }
  }

  // 开始轮询
  setTimeout(poll, interval)
}

// 获取分类列表
async function getCategoryList() {
  try {
    categoryLoading.value = true
    const response = await apiRequest('/productAnyShoot/template/category/list', {
      method: 'GET'
    })
    
    if (response && response.code === 200 && response.data) {
      // 英文到中文的翻译映射
      const categoryTranslations = {
        "Women's bottoms": "女士下装",
        "Dress": "连衣裙",
        "Women's top": "女士上装",
        "Women's socks": "女士袜子",
        "Women's shoes": "女士鞋子",
        "Men's top": "男士上装",
        "Men's bottoms": "男士下装",
        "Men's shoes": "男士鞋子",
        "Men's socks": "男士袜子",
        "Kids' Clothing": "儿童服装",
        "Necklace": "项链",
        "Hand jewelry": "手部饰品",
        "Foot jewelry": "脚部饰品",
        "Earrings": "耳环",
        "Ring": "戒指",
        "Creative templates": "创意模板",
        "Gloves": "手套",
        "Watch": "手表",
        "Home supplies": "家居用品",
        "Hair accessories": "发饰",
        "Hat": "帽子",
        "Scarf": "围巾",
        "Headphones": "耳机",
        "Belt": "腰带",
        "3C Digital Products": "3C数码产品",
        "Makeup": "化妆品",
        "Vitamins & Supplements": "维生素保健品",
        "Medications": "药品",
        "Sports Equipment": "运动器材",
        "Swimwear": "泳装",
        "Home Decor": "家居装饰",
        "Kitchenware": "厨具",
        "Sports & Outdoors": "运动户外",
        "Stationery & Office Supplies": "文具办公用品",
        "Maternal & Infant Products": "母婴用品",
        "Toys": "玩具",
        "Books": "书籍",
        "Food": "食品",
        "Beverages": "饮料",
        "Automotive&Motorcycle": "汽车摩托车",
        "Luggage": "行李箱包",
        "Personal Care Products": "个人护理用品",
        "Bag": "包包",
        "Furniture": "家具",
        "Home Appliances": "家用电器",
        "Pet Products": "宠物用品",
        "Glasses": "眼镜"
      }
      
      // 处理数据并翻译为中文
      categoryList.value = response.data.map(category => ({
        id: category.categoryId,
        name: categoryTranslations[category.categoryName] || category.categoryName
      }))
    }
  } catch (error) {
    console.error('获取分类列表失败:', error)
    ElMessage.error('获取分类列表失败')
  } finally {
    categoryLoading.value = false
  }
}

// 示例视频相关函数
// 已移除内嵌播放器逻辑

// 触发模特图上传
function triggerModelImageUpload() {
  if (modelUploadRef.value) {
    const uploadInput = modelUploadRef.value.$el.querySelector('input[type="file"]')
    if (uploadInput) {
      uploadInput.click()
    }
  }
}

// 获取模板列表
async function getTemplateList(isLoadMore = false) {
  if (!isLoadMore) {
    templatePageNo.value = 1
    templateHasMore.value = true
    templateList.value = []
  }

  if (!templateHasMore.value || templateLoading.value) return

  try {
    templateLoading.value = true
    const params = new URLSearchParams({
      pageNo: String(templatePageNo.value),
      pageSize: String(pageSize)
    })
    
    // 添加分类参数
    if (selectedCategory.value) {
      params.append('categoryIds', selectedCategory.value)
    }
    
    const response = await apiRequest(`/productAnyShoot/template/list?${params.toString()}`, {
      method: 'GET'
    })

    if (response?.code === 200 && response.data) {
      const { data, total } = response.data
      
      
      
      if (isLoadMore) {
        templateList.value = [...templateList.value, ...data]
      } else {
        templateList.value = data
      }

      templateHasMore.value = templateList.value.length < total
      
      if (templateHasMore.value) {
        templatePageNo.value++
      }
    }
  } catch (error) {
    console.error('获取模板列表失败:', error)
    ElMessage.error('获取模板列表失败')
  } finally {
    templateLoading.value = false
  }
}

// 打开数字人选择弹窗
function handleOpenDigitalHumanDialog(event) {
  // 阻止事件冒泡，防止触发上传
  if (event) {
    event.preventDefault()
    event.stopPropagation()
  }
  
  showDigitalHumanDialog.value = true
  // 重置临时选择状态
  selectedTemplateInDialog.value = null
  getCategoryList()
  getTemplateList()
}

// 处理分类切换
function handleCategoryChange(categoryId) {
  selectedCategory.value = categoryId
  getTemplateList()
}

// 获取模板的最佳图片URL
function getTemplateImageUrl(template) {
  // 优先使用 templateImageUrl，然后是 coverUrl，最后是 template_image_url
  const imageUrl = template.templateImageUrl || template.coverUrl || template.template_image_url
  return imageUrl
}

// 处理图片加载错误
function handleImageError(event) {
  // 可以设置一个默认图片
  event.target.src = ''
}

// 选择模版（临时选择）
function handleSelectTemplate(template) {
  selectedTemplateInDialog.value = template
}

// 确认数字人选择
function confirmDigitalHumanSelection() {
  if (!selectedTemplateInDialog.value) {
    ElMessage.warning('请先选择一个数字人模板')
    return
  }
  
  const template = selectedTemplateInDialog.value
  selectedTemplate.value = template
  
  // 获取统一的图片URL
  const imageUrl = getTemplateImageUrl(template)
  
  if (imageUrl) {
    // 检查图片是否已经在模板列表中加载过
    const existingImg = document.querySelector(`img[src="${imageUrl}"]`)
    
    if (existingImg && existingImg.complete) {
      // 图片已经加载完成，直接使用其尺寸信息
      originalModelSize.value = { 
        width: existingImg.naturalWidth, 
        height: existingImg.naturalHeight 
      }
      modelImageUrl.value = imageUrl
      // 初始化画布
      drawBg()
      initModelMaskCanvas()
      setTimeout(() => { resizeCanvasToImage() }, 100)
    } else {
      // 图片未加载完成，创建新的Image对象
      const img = new Image()
      img.onload = () => {
        originalModelSize.value = { width: img.width, height: img.height }
        // 初始化画布
        drawBg()
        initModelMaskCanvas()
        setTimeout(() => { resizeCanvasToImage() }, 100)
      }
      img.src = imageUrl
      // 设置模特图URL
      modelImageUrl.value = imageUrl
    }
    
    // 生成显示名称
    const displayName = getTemplateDisplayName(template)
    ElMessage.success(`已选择模板：${displayName}`)
    showDigitalHumanDialog.value = false
    
    console.log('选择的模板:', template)
  } else {
    ElMessage.error('该模板没有可用的预览图片')
  }
}

// 处理模板列表滚动
function handleTemplateScroll(e) {
  const { scrollHeight, scrollTop, clientHeight } = e.target
  // 滚动到底部时加载更多
  if (scrollHeight - scrollTop - clientHeight < 50 && !templateLoading.value && templateHasMore.value) {
    getTemplateList(true)
  }
}

// 清除模特图
function clearModelImage() {
  modelImageUrl.value = ''
  selectedTemplate.value = null
  modelImageFileId.value = '' // 清除上传的模特图文件ID
  originalModelSize.value = { width: 0, height: 0 }
  modelMaskCanvas.value = null
  
  // 清除画布
  const canvas = canvasRef.value
  if (canvas) {
    const ctx = canvas.getContext('2d')
    ctx.clearRect(0, 0, canvas.width, canvas.height)
  }
  
  ElMessage.success('已清除模特图')
}

// 跳转到任务列表
function goToTaskList() {
  // 根据当前路由决定跳转路径
  const currentRoute = router.currentRoute.value
  if (currentRoute.path.includes('/transfer-all/')) {
    router.push('/transfer-all/task-list')
  } else {
    router.push('/mask-editor/task-list')
  }
}

onMounted(() => {
  drawBg()
  
  // 监听窗口大小变化
  window.addEventListener('resize', () => {
    setTimeout(resizeCanvasToImage, 100)
  })
})

onUnmounted(() => {
  window.removeEventListener('resize', resizeCanvasToImage)
})
</script>

<style scoped>
.mask-editor {
  display: flex;
  height: 100vh;
  background: #18181c;
  gap: 10px;
}
.sidebar {
  width: 480px;
  background: #23232a;
  padding: 24px 30px;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.product-image-section {
  margin-bottom: 24px;
}
.image-wrapper {
  position: relative;
  width: 350px;
  height: 350px;
  border-radius: 12px;
  overflow: hidden;
}
.upload {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.preview-img, .upload-placeholder {
  width: 350px;
  height: 350px;
  object-fit: contain;
  background: #222;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.upload-placeholder {
  color: #aaa;
  font-size: 16px;
  text-align: center;
}
.tools {
  margin-top: 32px;
  width: 100%;
}
.slider-label {
  margin: 16px 0 8px 0;
  color: #fff;
  font-size: 14px;
}
.canvas-area {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: #18181c;
  position: relative;
  min-width: 0;
}
.canvas-header {
  color: #fff;
  font-size: 15px;
  font-weight: 500;
  margin: 12px 0 6px 24px;
}
.canvas-main {
  flex: 1;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 500px;
  max-height: calc(100vh - 200px);
  padding-bottom: 100px;
}
.canvas-bg-checkerboard {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 500px;
  height: 580px;
  transform: translate(-50%, -50%);
  background: repeating-conic-gradient(#222 0% 25%, #2a2a2a 0% 50%) 50% / 40px 40px;
  border-radius: 18px;
  z-index: 0;
}
.upload-center {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
}
.upload-center-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 16px;
}
.upload-center-btn:hover {
  color: #409eff;
}
.upload-divider {
  font-size: 14px;
  color: #666;
  margin: 8px 0;
  position: relative;
  width: 100%;
  text-align: center;
}

.upload-divider::before,
.upload-divider::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 35%;
  height: 1px;
  background: #444;
}

.upload-divider::before {
  left: 0;
}

.upload-divider::after {
  right: 0;
}
.canvas-img-wrap {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.model-image-container {
  position: relative;
  display: inline-block;
}
.canvas-img {
  max-width: 480px;
  max-height: 560px;
  object-fit: contain;
  border-radius: 12px;
  box-shadow: 0 2px 16px #000a;
  background: transparent;
  display: block;
}
.mask-canvas {
  position: absolute;
  left: 0;
  top: 0;
  border-radius: 12px;
  background: transparent;
  cursor: crosshair;
  pointer-events: auto;
}
.canvas-actions {
  position: absolute;
  right: 32px;
  bottom: 32px;
  z-index: 10;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.canvas-footer-bar {
  position: sticky;
  bottom: 0;
  left: 0;
  right: 0;
  background: #23232a;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 32px 8px 32px;
  z-index: 20;
  border-radius: 0 0 18px 18px;
  box-shadow: 0 -2px 12px #0003;
  height: 80px;
}
.footer-left, .footer-center, .footer-right {
  display: flex;
  align-items: center;
}
.footer-center {
  flex: 1;
  justify-content: center;
}
.generate-btn {
  min-width: 160px;
  height: 40px;
  font-size: 16px;
  font-weight: 600;
  margin: 0 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #409eff !important;
  border: none !important;
  color: #fff !important;
  border-radius: 14px !important;
  box-shadow: 0 4px 16px rgba(64, 158, 255, 0.4) !important;
  transition: all 0.3s ease !important;
  position: relative;
  padding-right: 80px !important;
}
.generate-btn:hover {
  background: #66b1ff !important;
  transform: translateY(-2px) !important;
  box-shadow: 0 8px 28px rgba(64, 158, 255, 0.6) !important;
}
.points-text {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 12px;
  opacity: 1;
  padding-left: 12px;
  border-left: 1px solid rgba(255, 255, 255, 0.5);
}
.footer-right {
  display: flex;
  align-items: center;
  gap: 12px;
}
.template-btn, .task-list-btn {
  min-width: 120px;
  font-size: 16px;
  font-weight: 600;
  background-color: #333;
  color: #fff;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.template-btn::before {
  content: "📄";
}
.task-list-btn {
  background: #409eff !important;
  border: none !important;
  color: #fff !important;
  min-width: 140px;
  font-size: 14px;
  font-weight: 500;
}
.task-list-btn:hover {
  background: #66b1ff !important;
}
.product-mask-canvas {
  position: absolute;
  left: 0;
  top: 0;
  width: 350px;
  height: 350px;
  cursor: crosshair;
  z-index: 2;
  border-radius: 12px;
  background: transparent;
  pointer-events: auto;
}
.preview-img {
  width: 350px;
  height: 350px;
  object-fit: contain;
  background: #222;
  border-radius: 12px;
  display: block;
  position: relative;
  z-index: 1;
}
.upload-placeholder {
  width: 350px;
  height: 350px;
  object-fit: contain;
  background: #222;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #aaa;
  font-size: 16px;
  text-align: center;
}

/* 数字人选择弹窗样式 */
:deep(.digital-human-dialog) {
  --el-dialog-bg-color: #23232a;
  --el-bg-color: #23232a;
  --el-text-color-primary: #ffffff;
  --el-border-color: #2a2a2a;
}

:deep(.digital-human-dialog .el-dialog) {
  background: #23232a !important;
  border-radius: 20px;
  border: 1px solid #2a2a2a;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.8);
}

:deep(.digital-human-dialog .el-dialog__header) {
  background: #2a2a2a !important;
  border-radius: 20px 20px 0 0;
  padding: 20px 24px;
  border-bottom: 1px solid #32323a;
}

:deep(.digital-human-dialog .el-dialog__title) {
  color: white !important;
  font-size: 18px;
  font-weight: 600;
}

:deep(.digital-human-dialog .el-dialog__body) {
  padding: 24px;
  background: #23232a !important;
  color: #fff !important;
}

:deep(.digital-human-dialog .el-dialog__footer) {
  background: #23232a !important;
  border-radius: 0 0 20px 20px;
  padding: 20px 24px;
  border-top: 1px solid #32323a;
}

:deep(.digital-human-dialog .el-button) {
  background: #18181c !important;
  border: 1px solid #409eff !important;
  color: #fff !important;
}

:deep(.digital-human-dialog .el-button:hover) {
  background: #409eff !important;
  border-color: #409eff !important;
  color: #fff !important;
}

:deep(.digital-human-dialog .el-dialog__close) {
  color: #909399 !important;
  background: transparent !important;
}

:deep(.digital-human-dialog .el-dialog__close:hover) {
  color: #fff !important;
  background: rgba(255, 255, 255, 0.1) !important;
}

:deep(.digital-human-dialog .el-dialog__headerbtn) {
  background: transparent !important;
}

:deep(.digital-human-dialog .el-overlay) {
  background-color: rgba(0, 0, 0, 0.8) !important;
}

/* 确保弹窗内所有元素都是暗色 */
:deep(.digital-human-dialog *) {
  color: inherit;
}

:deep(.digital-human-dialog .el-scrollbar) {
  background: transparent !important;
}

:deep(.digital-human-dialog .el-scrollbar__wrap) {
  background: transparent !important;
}

:deep(.digital-human-dialog .el-scrollbar__view) {
  background: transparent !important;
}

.category-section {
  margin-bottom: 24px;
}

.section-subtitle {
  margin: 0 0 16px;
  font-size: 16px;
  font-weight: 600;
  color: #fff;
}

.category-list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding: 16px;
  background: #2a2a2a;
  border-radius: 12px;
}

.category-item {
  padding: 8px 16px;
  background: #18181c;
  border: 1px solid #409eff;
  border-radius: 20px;
  color: #ffffff;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s;
}

.category-item:hover {
  background: #409eff;
  color: #fff;
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.3);
}

.category-item.active {
  background: #409eff;
  color: #fff;
  box-shadow: 0 2px 12px rgba(64, 158, 255, 0.4);
}

.category-item.disabled {
  cursor: not-allowed;
  opacity: 0.6;
  color: #666666;
  border-color: #333333;
  background: #18181c;
}

.category-item.disabled:hover {
  transform: none;
  box-shadow: none;
  background: #18181c;
  color: #666666;
}

.template-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 20px;
  max-height: 500px;
  overflow-y: auto;
  padding: 8px;
}

.template-grid::-webkit-scrollbar {
  width: 8px;
}

.template-grid::-webkit-scrollbar-track {
  background: #18181c;
  border-radius: 4px;
}

.template-grid::-webkit-scrollbar-thumb {
  background: linear-gradient(45deg, #409eff, #66b1ff);
  border-radius: 4px;
}

.template-card {
  background: #2a2a2a;
  border-radius: 12px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border: 1px solid #32323a;
  position: relative;
}

.template-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 20px rgba(64, 158, 255, 0.2);
  border-color: #409eff;
}

.template-card.selected {
  border-color: #409eff;
  box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.4);
  background: #1a1a1a;
  transform: translateY(-4px);
  position: relative;
}

.template-card.selected::before {
  content: '✓';
  position: absolute;
  top: 8px;
  right: 8px;
  width: 24px;
  height: 24px;
  background: #409eff;
  color: white;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: bold;
  z-index: 10;
  animation: fadeIn 0.3s ease;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.4);
}

.template-card.selected .template-image {
  filter: brightness(1.1);
}

.template-card.selected .template-name {
  color: #409eff;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: scale(0.8);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.template-image {
  width: 100%;
  height: 150px;
  overflow: hidden;
}

.template-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.template-info {
  padding: 12px;
}

.template-name {
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  margin-bottom: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.template-desc {
  font-size: 12px;
  color: #909399;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.loading-more {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 20px;
  color: #909399;
}

.image-source-info {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.7);
  padding: 8px 12px;
  border-radius: 0 0 12px 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: #fff;
  font-size: 12px;
  pointer-events: none; /* 不阻挡鼠标事件 */
  z-index: 1; /* 确保在画布之上但不阻挡交互 */
}

.image-source-info span {
  color: #fff;
  font-weight: 500;
}

.clear-btn {
  background: #ff4757 !important;
  color: #fff !important;
  border: none !important;
  padding: 4px 8px;
  border-radius: 4px;
  pointer-events: auto; /* 清除按钮可以点击 */
  cursor: pointer;
  transition: background 0.2s;
  font-size: 11px;
}

.clear-btn:hover {
  background: #ff6b7a !important;
}

/* 统一的上传按钮样式 */
.upload-product-btn-prominent,
.upload-model-btn-prominent,
.select-digital-human-btn-prominent {
  background: linear-gradient(135deg, #409eff, #66b1ff) !important;
  border: none !important;
  color: #fff !important;
  padding: 14px 28px !important;
  border-radius: 10px !important;
  font-size: 14px !important;
  font-weight: 600 !important;
  box-shadow: 0 4px 16px rgba(64, 158, 255, 0.4) !important;
  transition: all 0.3s ease !important;
  margin-bottom: 10px !important;
  width: 100% !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 8px !important;
}

.upload-product-btn-prominent:hover,
.upload-model-btn-prominent:hover,
.select-digital-human-btn-prominent:hover {
  background: linear-gradient(135deg, #66b1ff, #409eff) !important;
  transform: translateY(-2px) !important;
  box-shadow: 0 8px 24px rgba(64, 158, 255, 0.6) !important;
}

/* 产品图上传区域样式调整 */
.upload-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 350px;
  width: 350px;
  padding: 20px;
  box-sizing: border-box;
}


</style> 